package com.behelpful.common.core.utils;

import lombok.experimental.UtilityClass;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 字符串工具类
 *
 * @author Alay
 * @date 2021-12-10 14:24
 */
@UtilityClass
public class IStrUtil {

    private static final Pattern LINE_PATTERN = Pattern.compile("_(\\w)");
    private static final Pattern HUMP_PATTERN = Pattern.compile("[A-Z]");


    /**
     * 首字母转大写
     *
     * @param str
     * @return
     */
    public String fistUpCase(String str) {
        int strLen;
        return str != null && (strLen = str.length()) != 0 ? (new StringBuffer(strLen)).append(Character.toUpperCase(str.charAt(0))).append(str.substring(1)).toString() : str;
    }

    /**
     * 首字母转小写
     *
     * @param str
     * @return
     */
    public String fistLowCase(String str) {
        int strLen;
        return str != null && (strLen = str.length()) != 0 ? (new StringBuffer(strLen)).append(Character.toLowerCase(str.charAt(0))).append(str.substring(1)).toString() : str;
    }

    /**
     * 下划线转 小驼峰
     */
    public String line2Hump(String str) {
        str = str.toLowerCase();
        Matcher matcher = LINE_PATTERN.matcher(str);
        StringBuffer sb = new StringBuffer();
        while (matcher.find()) {
            matcher.appendReplacement(sb, matcher.group(1).toUpperCase());
        }
        matcher.appendTail(sb);
        return sb.toString();
    }


    /**
     * 驼峰转下划线
     */
    public String hump2Line(String str) {
        // 首字母转小写
        str = str.substring(0, 1).toLowerCase() + str.substring(1);
        Matcher matcher = HUMP_PATTERN.matcher(str);
        StringBuffer sb = new StringBuffer();
        while (matcher.find()) {
            matcher.appendReplacement(sb, "_" + matcher.group(0).toLowerCase());
        }
        matcher.appendTail(sb);
        return sb.toString();
    }


    /**
     * 字符串相似度百分比
     *
     * @param str1         字符串1
     * @param str2         字符串2
     * @param isIgnoreCase 是否忽略大小写
     * @return
     */
    public static float similarityRate(String str1, String str2, boolean isIgnoreCase) {
        int maxLength = str1.length() > str2.length() ? str1.length() : str2.length();
        if (maxLength == 0) {
            return 1;
        } else {
            return 1 - (float) compare(str1, str2, isIgnoreCase) / maxLength;
        }
    }

    /**
     * 字符串相似度
     *
     * @param str1         字符串1
     * @param str2         字符串2
     * @param isIgnoreCase 是否忽略大小写
     * @return
     */
    private static int compare(String str1, String str2, boolean isIgnoreCase) {
        int d[][]; // 矩阵
        int n = str1.length();
        int m = str2.length();
        int i; // 遍历str的
        int j; // 遍历target的
        char ch1; // str的
        char ch2; // target的
        int temp; // 记录相同字符,在某个矩阵位置值的增量,不是0就是1
        if (n == 0) {
            return m;
        }
        if (m == 0) {
            return n;
        }
        d = new int[n + 1][m + 1];
        // 初始化第一列
        for (i = 0; i <= n; i++) {
            d[i][0] = i;
        }
        // 初始化第一行
        for (j = 0; j <= m; j++) {
            d[0][j] = j;
        }
        // 遍历str
        for (i = 1; i <= n; i++) {
            ch1 = str1.charAt(i - 1);
            // 去匹配target
            for (j = 1; j <= m; j++) {
                ch2 = str2.charAt(j - 1);
                if (isIgnoreCase) {
                    if (ch1 == ch2 || ch1 == ch2 + 32 || ch1 + 32 == ch2) {
                        temp = 0;
                    } else {
                        temp = 1;
                    }
                } else {
                    if (ch1 == ch2) {
                        temp = 0;
                    } else {
                        temp = 1;
                    }
                }
                // 左边+1,上边+1, 左上角+temp取最小
                d[i][j] = min(d[i - 1][j] + 1, d[i][j - 1] + 1, d[i - 1][j - 1] + temp);
            }
        }
        return d[n][m];
    }

    private static int min(int one, int two, int three) {
        return (one = one < two ? one : two) < three ? one : three;
    }

}
